﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using AutoMapper;
using App.Web.References;
using App.Core.Entities;
using App.Core.Entities.Foundation;
using App.Dto.Dtos;

namespace App.Web.Mapping
{
    public class MappingDefinitions
    {
        public void Initialise()
        {
            AutoRegistrations();
        }

        private void AutoRegistrations()
        {
            List<Type> entityTypes =
                ReferencedAssemblies.Domain.
                    GetTypes().Where(x => !x.Name.Equals(value: "BaseEntity", comparisonType: StringComparison.OrdinalIgnoreCase)&& !x.Name.Equals(value: "IEntity", comparisonType: StringComparison.OrdinalIgnoreCase)&& x.Name.EndsWith("Entity", true, CultureInfo.InvariantCulture)).ToList();

            List<Type> dtoTypes =
                ReferencedAssemblies.Dto.
                GetTypes().Where(x => x.Name.EndsWith(value: "Dto", ignoreCase: true, culture: CultureInfo.InvariantCulture)).ToList();
             
            var config = new MapperConfiguration(cfg => { }); 
            Mapper.Initialize(cfg => {
                cfg.AllowNullDestinationValues = false;
                cfg.CreateMap<string, int>().ConstructUsing(source => { return Int32.Parse(source); });
                cfg.CreateMap<string, DateTime>().ConstructUsing(source => { return DateTime.Parse(source); });
                cfg.CreateMap<DateTime, string>().ConstructUsing(source => { return source.ToString("yyyy-MM-dd HH:mm:ss"); });
                cfg.CreateMap<string, Decimal>().ConstructUsing(source => { return Decimal.Parse(source); });
                 
                foreach (var dto in dtoTypes)
                {
                    string dtoName = dto.Name; 

                    IList<string> entityNames = new List<string>();
                    entityNames.Add(dtoName.Replace("Dto", "Entity"));

                    object[] attributes = dto.GetCustomAttributes(false);
                    if (attributes != null)
                    {
                        foreach (var attr in attributes)
                        {
                            if (attr is ToEntityAttribute)
                            {
                                var toEntity = attr as ToEntityAttribute;
                                string[] entityNameByAttrs = toEntity.EntityName.Split(',');
                                foreach (var entityName in entityNameByAttrs)
                                {
                                    if (String.IsNullOrEmpty(entityName))
                                        continue;
                                    entityNames.Add(entityName);
                                }
                            }
                        }
                    }
                    entityNames = entityNames.Distinct().ToList();
                    foreach (var entityName in entityNames)
                    {
                        Type entityType = entityTypes.FirstOrDefault(x => x.Name == entityName);
                        if (entityType != null)
                        {
                            cfg.CreateMap(dto, entityType);
                            cfg.CreateMap(entityType, dto);
                        }
                    } 
                }
            });  
        } 
    }
}